#include "stdafx.h"


Station::Station(int machineCount, Distribution* dist, QueueInterface<>* queue) : machineCount(machineCount), distribution(dist), queue(queue)
{
	machines = new pair<double,int>[machineCount]();
	waitingQueue = new QueueInterface<pair<Station*, int>>(QueueInterface<>::FIFO, INT_MAX);
}

Station::~Station(void)
{
}

void Station::linkToStation(Station* station, double chance) {
	nextStations.push_back(pair<Station*, double>(station, chance));
}

void Station::timeTrigger(double time, Scheduler* scheduler) {
	int mId=0;
	while(mId<machineCount) {
		if(machines[mId].first == time) break;
		else mId++;
	}

	double nextRand = (double)rand()/RAND_MAX;
	double chanceSum = 0;
	int sId=-1;
	do {
		chanceSum+=nextStations[++sId].second;
	} while(chanceSum<nextRand);

	if(nextStations[sId].first->putItem(pair<double, int>(time, machines[mId].second), this, scheduler)) {
		machines[mId] = pair<double, int>(0,0);
		if(queue->getLength() > 0) {
			machines[mId] = pair<double, int>(time+distribution->generate() , queue->get());
			scheduler->addTrigger(machines[mId].first, this);
			queue->pop();	
		}
		if(waitingQueue->getLength() > 0) {
			if(waitingQueue->get().first->pull(waitingQueue->get().second)) {
				putItem(pair<double, int>(time, waitingQueue->get().second), waitingQueue->get().first, scheduler);
				waitingQueue->pop();
			}
		}
	}
}

bool Station::pull(int item) {
	int mId=0;
	while(mId<machineCount) {
		if(machines[mId].second == item) {
			machines[mId] = pair<double,int>(0,0);
			return true;
		}else
			mId++;
	}

	return false;
}

	bool Station::putItem(pair<double, int> item, Station* fromStation, Scheduler* scheduler) {
		int mId=0;
		while(mId<machineCount) {
			if(machines[mId].first == 0) {
				item.first += distribution->generate();
				machines[mId] = item;
				scheduler->addTrigger(item.first, this);
				return true;
			} else mId++;
		}

		if(queue->push(item.second))
			return true;
		else {
			waitingQueue->push(make_pair(fromStation,item.second));
			return false;
		}
	}

	void Station::normalizeLinks() {
		double sum = 0;
		for(pair<Station*, double> station: nextStations) {
			sum+=station.second;
		}
		for(pair<Station*, double> station: nextStations) {
			station.second/=sum;
		}

	}